
/**
 * This class implements all the methods for 3a code generation.
 * @author MLB
 *
 */
public class Code3aGenerator{
	private static boolean error = false;

	public Code3aGenerator() {
		
	}
    /**
     * Generates the 3a statement: VAR t
     **/
	public static Code3a genVar(Operand3a t) {
		Inst3a i = new Inst3a(Inst3a.TAC_VAR, t, null, null);
		return new Code3a(i);
	}
    /**
     * Generate code for a binary operation
     * @param op must be a code op: Inst3a.TAC_XXX
     */
	public static Code3a genBinOp(int op, ExpressionAttribute exp1, ExpressionAttribute exp2,
			Operand3a temp) {
		Code3a cod = exp1.code;
		cod.append(exp2.code);
		cod.append(genVar(temp));
		Inst3a i = new Inst3a(op, temp, exp1.place, exp2.place);
		cod.append(new Code3a(i));
		return cod;
	}

	public static Code3a genAssign(ExpressionAttribute exp1, ExpressionAttribute exp2){
		Code3a cod = exp1.code;
		Inst3a i = new Inst3a(Inst3a.TAC_COPY, exp2.place, exp1.place,null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genAssignArrayLeft(ExpressionAttribute exp1,VarAttribute var, ExpressionAttribute exp2){
		Code3a cod = exp2.code;
		cod.append(exp1.code);
		Inst3a i = new Inst3a(Inst3a.TAC_VARTAB, var, exp2.place,exp1.place);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genAssignArrayRight(VarAttribute var, VarAttribute var2, ExpressionAttribute exp){
		Code3a cod = exp.code;
		Inst3a i = new Inst3a(Inst3a.TAC_TABVAR, var, var2,exp.place);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genIfThenElse(ExpressionAttribute exp, Code3a cod1, Code3a cod2){
		Code3a cod= exp.code;
		LabelAttribute ELSE = SymbDistrib.newLabel();
		LabelAttribute FI = SymbDistrib.newLabel();
		Inst3a i = new Inst3a(Inst3a.TAC_IFZ,exp.place ,ELSE ,null);
		cod.append(i);
		cod.append(cod1);
		i = new Inst3a(Inst3a.TAC_GOTO,FI ,null, null);
		cod.append(i);
		i = new Inst3a(Inst3a.TAC_LABEL,ELSE ,null, null);
		cod.append(i);
		cod.append(cod2);
		i = new Inst3a(Inst3a.TAC_LABEL,FI ,null, null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genIfThen(ExpressionAttribute exp, Code3a cod1){
		Code3a cod= exp.code;
		LabelAttribute FI = SymbDistrib.newLabel();
		Inst3a i = new Inst3a(Inst3a.TAC_IFZ,exp.place ,FI ,null);
		cod.append(i);
		cod.append(cod1);
		i = new Inst3a(Inst3a.TAC_LABEL,FI ,null, null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genWhile(ExpressionAttribute exp, Code3a code){
		LabelAttribute WHILE = SymbDistrib.newLabel();
		LabelAttribute DONE = SymbDistrib.newLabel();
		Code3a cod = new Code3a();
		Inst3a i = new Inst3a(Inst3a.TAC_LABEL,WHILE ,null ,null);
		cod.append(i);
		cod.append(exp.code);
		i = new Inst3a(Inst3a.TAC_IFZ,exp.place ,DONE ,null);
		cod.append(i);
		cod.append(code);
		i = new Inst3a(Inst3a.TAC_GOTO,WHILE ,null, null);
		cod.append(i);
		i = new Inst3a(Inst3a.TAC_LABEL,DONE ,null, null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genReturn(ExpressionAttribute exp){
		Code3a cod = exp.code;
		Inst3a i = new Inst3a(Inst3a.TAC_RETURN,exp.place ,null ,null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genArgFonction(ExpressionAttribute exp){
		Code3a cod = exp.code;
		Inst3a i = new Inst3a(Inst3a.TAC_ARG,exp.place ,null ,null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genCallFunc(Code3a code, VarAttribute var){
		Code3a cod = code;
		Inst3a i = new Inst3a(Inst3a.TAC_CALL,null ,var ,null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genCallFuncRet(Code3a code, VarAttribute var1, VarAttribute var2){
		Code3a cod = code;
		Inst3a i = new Inst3a(Inst3a.TAC_CALL,var2 ,var1 ,null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genPrintItemText(String chaine){
		Code3a cod = new Code3a();
		chaine = chaine.substring(1,(chaine.length()-1));
		//System.out.println(chaine);
		Data3a data = new Data3a(chaine);
		cod.appendData(data);
		Inst3a i = new Inst3a(Inst3a.TAC_ARG,data.getLabel() ,null ,null);
		cod.append(i);
		LabelAttribute var = new LabelAttribute("L4");
		i = new Inst3a(Inst3a.TAC_CALL,null, var, null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genPrintItemExp(ExpressionAttribute exp){
		Code3a cod = exp.code;
		Inst3a i = new Inst3a(Inst3a.TAC_ARG,exp.place ,null ,null);
		cod.append(i);
		LabelAttribute var = new LabelAttribute("L2");
		i = new Inst3a(Inst3a.TAC_CALL,null, var, null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genDebFunc(VarAttribute var){
		Code3a cod = new Code3a();
		Inst3a i = new Inst3a(Inst3a.TAC_LABEL,var ,null ,null);
		cod.append(i);
		i = new Inst3a(Inst3a.TAC_BEGINFUNC,null ,null ,null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genFinFunc(){
		Code3a cod = new Code3a();
		Inst3a i = new Inst3a(Inst3a.TAC_ENDFUNC,null ,null ,null);
		cod.append(i);
		return cod;
	}
	
	public static Code3a genReadItem(VarAttribute v){
		Code3a cod = new Code3a();
		LabelAttribute var = new LabelAttribute("L8");
		Inst3a i = new Inst3a(Inst3a.TAC_CALL,v, var, null);
		cod.append(i);
		return cod;
	}
} // Code3aGenerator ***
